#ifndef LOCAL_H
#define LOCAL_H

#include "inc/uclean.h"
#include "inc/utypes.h"
#include "inc/ucnv.h"

/*
 * Code within ICU that accesses shared static or global data should
 * instantiate a Mutex object while doing so.  The unnamed global mutex
 * is used throughout ICU, so keep locking short and sweet.
 *
 * For example:
 *
 * void Function(int arg1, int arg2)
 * {
 *   static Object* foo;     // Shared read-write object
 *   umtx_lock(NULL);        // Lock the ICU global mutex
 *   foo->Method();
 *   umtx_unlock(NULL);
 * }
 *
 * an alternative C++ mutex API is defined in the file common/mutex.h
 */

/* Lock a mutex.
 * @param mutex The given mutex to be locked.  Pass NULL to specify
 *              the global ICU mutex.  Recursive locks are an error
 *              and may cause a deadlock on some platforms.
 */
U_CAPI void U_EXPORT2 umtx_lock   ( UMTX* mutex );

/* Unlock a mutex. Pass in NULL if you want the single global
   mutex.
 * @param mutex The given mutex to be unlocked.  Pass NULL to specify
 *              the global ICU mutex.
 */
U_CAPI void U_EXPORT2 umtx_unlock ( UMTX* mutex );

/* Initialize a mutex. Use it this way:
   umtx_init( &aMutex );
 * ICU Mutexes do not need explicit initialization before use.  Use of this
 *   function is not necessary.
 * Initialization of an already initialized mutex has no effect, and is safe to do.
 * Initialization of mutexes is thread safe.  Two threads can concurrently
 *   initialize the same mutex without causing problems.
 * @param mutex The given mutex to be initialized
 */
U_CAPI void U_EXPORT2 umtx_init   ( UMTX* mutex );

/* Destroy a mutex. This will free the resources of a mutex.
 * Use it this way:
 *   umtx_destroy( &aMutex );
 * Destroying an already destroyed mutex has no effect, and causes no problems.
 * This function is not thread safe.  Two threads must not attempt to concurrently
 *   destroy the same mutex.
 * @param mutex The given mutex to be destroyed.
 */
U_CAPI void U_EXPORT2 umtx_destroy( UMTX *mutex );

/**
 * This should align the memory properly on any machine.
 * This is very useful for the safeClone functions.
 */
typedef union {
    long    t1;
    double  t2;
    void   *t3;
} UAlignedMemory;

/**
 * Get the amount of bytes that a pointer is off by from
 * the previous aligned pointer
 */
#define U_ALIGNMENT_OFFSET(ptr) (((size_t)ptr) & (sizeof(UAlignedMemory) - 1))

/**
 * Get the amount of bytes to add to a pointer
 * in order to get the next aligned address
 */
#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))

#define UMTX_CHECK(pMutex, expression, result) \
    (result)=(expression);

#endif

EXTERN_C const char* icupub_getDefaultCodepage();
EXTERN_C PVoid icupub_ReadFile(const char* path);

U_CAPI UConverter* U_EXPORT2
ucnv_internal_open(const char *name, UErrorCode * err);
U_CAPI void  U_EXPORT2
ucv_internal_close(const char *name, UConverter *converter);
